  /******************************************************************************
  * @file    PT32X005_uart.c
  * @author  应用开发团队
  * @version V1.1.0
  * @date    2020/1/27
  * @brief    This file provides firmware functions to manage the following
  *          functionalities of the Universal synchronous asynchronous receiver
  *          transmitter (UART):
  *           + Initialization and Configuration
  *           + STOP Mode
  *           + BaudRate
  *           + Data transfers
  *           + Multi-Processor Communication
  *           + Half-duplex mode
  *           + Smartcard mode
  *           + Interrupts and flags management
  *
  ******************************************************************************
  * @attention
  *
  *
  *****************************************************************************/


/* Includes ------------------------------------------------------------------*/
#include "PT32X005_uart.h"


/** @defgroup UART
  * @brief UART driver modules
  * @{
  */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/


/**
  * @brief  Initializes the UARTx peripheral according to the specified
  *         parameters in the UART_InitStruct .
  * @param  UARTx: where x can be from 0 to 1 to select the UART peripheral.
  * @param  UART_InitStruct: pointer to a UART_InitTypeDef structure that contains
  *         the configuration information for the specified UART peripheral.
  * @retval None
  */
void UART_Init(UART_TypeDef* UARTx, UART_InitTypeDef* UART_InitStruct)
{
	u32  tmpreg = 0, pclk = 0;
	/* Check the parameters */
	assert_param(IS_UART_ALL_PERIPH(UARTx));
	assert_param(IS_UART_BR_VAL(UART_InitStruct->UART_BaudRate));
	assert_param(IS_UART_WP_SEL(UART_InitStruct->UART_WordLength));
	assert_param(IS_UART_STOP_SEL(UART_InitStruct->UART_StopBits));
	assert_param(IS_UART_PS_SEL(UART_InitStruct->UART_Parity));
	assert_param(IS_UART_RE_SEL(UART_InitStruct->UART_Mode));
	assert_param(IS_UART_LoopBack_SEL(UART_InitStruct->UART_LoopBack));
	UARTx->RXFR = 0x00;
	UARTx->TXFR = 0x00;

	tmpreg &= ~(UART_CR_WP | UART_CR_STOP | UART_CR_PS | UART_CR_LPB | UART_CR_RE | UART_CR_RE);
	tmpreg |= 	(UART_InitStruct ->UART_WordLength | \
				UART_InitStruct ->UART_StopBits | \
				UART_InitStruct ->UART_Parity | \
				UART_InitStruct->UART_LoopBack | \
				UART_InitStruct->UART_Mode);
	UARTx->CR = tmpreg;

	pclk = RCC_GetSYSCLKFreq();
	UARTx->BRR = ( (pclk / 16) / UART_InitStruct->UART_BaudRate);
}


/**
  * @brief  Fills each UART_InitStruct member with its default value.
  * @param  UART_InitStruct: pointer to a UART_InitTypeDef structure
  *         which will be initialized.
  * @retval None
  */
void UART_StructInit(UART_InitTypeDef* UART_InitStruct)
{
	/* UART_InitStruct members default value */
	UART_InitStruct->UART_BaudRate = 19200;
	UART_InitStruct->UART_WordLength = UART_WP_8D;
	UART_InitStruct->UART_StopBits = UART_STOP_1b;
	UART_InitStruct->UART_Parity = UART_PS_ODD;
	UART_InitStruct->UART_Mode = UART_RE_Enable;
	UART_InitStruct->UART_LoopBack=UART_LoopBack_Disable;
}

/**
  * @brief  Enables or disables the specified UART peripheral.
  * @param  UARTx: where x can be from 0 to 1 to select the UART peripheral.
  * @param  NewState: new state of the UARTx peripheral.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void UART_Cmd(UART_TypeDef* UARTx, FunctionalState NewState)
{
	/* Check the parameters */
	assert_param(IS_UART_ALL_PERIPH(UARTx));
	assert_param(IS_FUNCTIONAL_STATE(NewState));
	if (NewState != DISABLE)
	{
		/* Enable the selected UART by setting the UE bit in the CR1 register */
		UARTx->CR |= UART_CR_UE;
	}
	else
	{
		/* Disable the selected UART by clearing the UE bit in the CR1 register */
		UARTx->CR &= (u32)~((u32)UART_CR_UE);
	}
}

/**
  * @brief  Transmits single data through the UARTx peripheral.
  * @param  UARTx: where x can be from 0 or 1 to select the UART peripheral.
  * @param  Data: the data to transmit.
  * @retval None
  */
void UART_SendData(UART_TypeDef* UARTx, u16 Data)
{
	/* Check the parameters */
	assert_param(IS_UART_ALL_PERIPH(UARTx));
	assert_param(IS_UART_DATA(Data));
	/* While the TxFIFO contain 8 characters. */
	while((UARTx->SR & UART_SR_TXF));
	/* Transmit Data */
	UARTx->DR = (Data & (u16)0x01FF);
}

/**
  * @brief  Transmits single string through the UARTx peripheral.
  * @param  UARTx: where x can be from 0 or 1 to select the UART peripheral.
  * @param  String: Pointer to the string to transmit.
  * @retval None
  */

void UART_StringSend(UART_TypeDef* UARTx, u8 *String)
{
	while(*String != '\0')
	{
		while((UARTx->SR & UART_SR_TXF));
		UART_SendData(UARTx, *String);
		String++;
	}
	UART_SendData(UARTx, 0x00);
}


/**
  * @brief  Returns the most recent received data by the UARTx peripheral.
  * @param  UARTx: where x can be from 0 to 1 to select the UART peripheral.
  * @retval The received data.
  */
u16 UART_ReceiveData(UART_TypeDef* UARTx)
{
	/* Check the parameters */
	assert_param(IS_UART_ALL_PERIPH(UARTx));
	/* Receive Data */
	return (u16)(UARTx->DR & (u16)0x01FF);
}


/**
  * @brief  This function reset the Rx and the Tx FIFOs
  * @param  UARTx: where x can be from 0 to 1 to select the UART peripheral.
  * @param  FIFO: Transmit FIFO or receive FIFO for the UART .
  *          This parameter can be:
  *            @arg Rx_FIFO: Receive FIFO .
  *            @arg Tx_FIFO: Transmit FIFO .
  * @retval None.
  */
void UART_FifoReset(UART_TypeDef * UARTx,  UART_FifoTypeDef FIFO)
{
	switch (FIFO)
	{
		case Rx_FIFO :
			UARTx->RXFR = UART_RXFR_RXFR;
			break;
		case Tx_FIFO :
			UARTx->TXFR = UART_TXFR_TXFR;
			break;
	}
}

/**
  * @brief  Enables or disables the UART's IrDA interface.
  * @param  UARTx: where x can be from 0 to 1 to select the UART peripheral.
  * @param  NewState: new state of the IrDA mode.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void UART_IrDACmd(UART_TypeDef* UARTx, FunctionalState NewState)
{
	/* Check the parameters */
	assert_param(IS_UART_ALL_PERIPH(UARTx));
	assert_param(IS_FUNCTIONAL_STATE(NewState));
	if (NewState != DISABLE)
	{
		/* Enable the IrDA mode by setting the EN bit in the IRR register */
		UARTx->IRC |= UART_IRC_IRE;
	}
	else
	{
		/* Disable the IrDA mode by clearing the EN bit in the IRR register */
		UARTx->IRC &= (u32)~((u32)UART_IRC_IRE);
	}
}

/**
  * @brief  Configures the IrDA's Pin polarity
  * @param  UARTx: where x can be from 0 to 1 to select the UART peripheral.
  * @param  Polarity: new defined levels for the UART data.
  *          This parameter can be:
  *            @arg UART_IrDAPolarity_Reverse: pin(s) signal values are inverted (Vdd =0, Gnd =1).
  *            @arg UART_IrDAPolarity_Norm: pin(s) signal works using the standard logic levels (Vdd =1, Gnd =0).
  * @retval None
  */
void UART_IrDAPolarityConfig(UART_TypeDef* UARTx, u16 Polarity)
{
	/* Check the parameters */
	assert_param(IS_UART_ALL_PERIPH(UARTx));
	assert_param(IS_UART_IrDAPolarity_SEL(Polarity));
	if (Polarity != (u16)UART_IrDAPolarity_Norm)
	{
		UARTx->IRC |= UART_IrDAPolarity_Reverse;
	}
	else
	{
		UARTx->IRC &= UART_IrDAPolarity_Norm;
	}
}

/**
  * @brief  Sets the system clock prescaler.
  * @param  UARTx: where x can be from 0 to 1 to select the UART peripheral.
  * @param  UART_DutyCycle: specifies the duty cycle  value(0~4095)
  * @retval None
  */
void UART_SetIrDADutyCycle(UART_TypeDef* UARTx, u16 UART_DutyCycle)
{
	/* Check the parameters */
	assert_param(IS_UART_ALL_PERIPH(UARTx));
	assert_param(IS_UART_DUTYCYCLE(UART_DutyCycle));
	/* Clear the IrDA's modulation PWM duty cycle */
	UARTx->IRDC &= ~UART_IRDC_DUTY;
	/* Set the IrDA's modulation PWM duty cycle*/
	UARTx->IRDC |= (u32)((u32)UART_DutyCycle);
}


/**
  * @brief  Enables or disables the UART's Half Duplex communication.
  * @param  UARTx: where x can be from 0 to 1 to select the UART peripheral.
  * @param  NewState: new state of the UART Communication.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void UART_HalfDuplexCmd(UART_TypeDef* UARTx, FunctionalState NewState)
{
	/* Check the parameters */
	assert_param(IS_UART_ALL_PERIPH(UARTx));
	assert_param(IS_FUNCTIONAL_STATE(NewState));
	if (NewState != DISABLE)
	{
		/* Enable the Half-Duplex mode by setting the OWE bit in the CR register */
		UARTx->CR |= UART_CR_OWE;
	}
	else
	{
		/* Disable the Half-Duplex mode by clearing the OWE bit in the CR register */
		UARTx->CR  &= (u32)~((u32)UART_CR_OWE);
	}
}

/**
  * @brief  Enables or disables the UART's transmitter or receiver.
  * @param  UARTx: where x can be from 0 to 1 to select the UART peripheral.
  * @param  UART_Direction: specifies the UART direction.
  *          This parameter can be any combination of the following values:
  *            @arg UART_OWD_TX: UART Transmitter
  *            @arg UART_OWD_RX: UART Receiver
  * @param  NewState: new state of the UART transfer direction.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void UART_HalfDuplexDirConfig(UART_TypeDef* UARTx, u32 UART_OWD_SEL)
{
	/* Check the parameters */
	assert_param(IS_UART_ALL_PERIPH(UARTx));
	assert_param(IS_UART_OWD_SEL(UART_OWD_SEL));
	if (UART_OWD_SEL != UART_OWD_RX)
	{
		/* Set NSS pin internally by software */
		UARTx->CR |= UART_OWD_TX;
	}
	else
	{
		/* Reset NSS pin internally by software */
		UARTx->CR &= UART_OWD_RX;
	}
}

/**
  * @brief  Enables or disables the specified UART interrupts.
  * @param  UARTx: where x can be from 0 to 1 to select the UART peripheral.
  * @param  UART_IT: specifies the UART interrupt sources to be enabled or disabled.
  *          This parameter can be one of the following values:
  *            @arg UART_IE_RXNEI
  *            @arg UART_IE_RXFI
  *            @arg UART_IE_PEI
  *            @arg UART_IE_FEI
  *            @arg UART_IE_OVRI
  *            @arg UART_IE_TXEI
  *            @arg UART_IE_TXFI
  *            @arg UART_IE_TXOI
  * @param  NewState: new state of the specified UARTx interrupts.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void UART_ITConfig(UART_TypeDef* UARTx, u32 UART_IT, FunctionalState NewState)
{
	/* Check the parameters */
	assert_param(IS_UART_ALL_PERIPH(UARTx));
	assert_param(IS_UART_IE_SEL(UART_IT));
	assert_param(IS_FUNCTIONAL_STATE(NewState));
	if (NewState != DISABLE)
	{
		UARTx->IE |= UART_IT;
	}
	else
	{
		UARTx->IE &= ~UART_IT;
	}
}

/**
  * @brief  Checks whether the specified UART flag is set or not.
  * @param  UARTx: where x can be from 0 to 1 to select the UART peripheral.
  * @param  UART_FLAG: specifies the flag to check.
  *          This parameter can be one of the following values:
  *            @arg UART_SR_RXNE
  *            @arg UART_SR_RXF
  *            @arg UART_SR_PE
  *            @arg UART_SR_FE
  *            @arg UART_SR_OVR
  *            @arg UART_SR_TXE
  *            @arg UART_SR_TXF
  *            @arg UART_SR_TXO
  * @retval The new state of UART_FLAG (SET or RESET).
  */
FlagStatus UART_GetFlagStatus(UART_TypeDef* UARTx, u32 UART_FLAG)
{
	FlagStatus bitstatus = RESET;
	/* Check the parameters */
	assert_param(IS_UART_ALL_PERIPH(UARTx));
	assert_param(IS_UART_SR_SEL(UART_FLAG));
	if ((UARTx->SR & UART_FLAG) != (u16)RESET)
	{
		bitstatus = SET;
	}
	else
	{
		bitstatus = RESET;
	}
	return bitstatus;
}

/**
  * @brief  Clears the UARTx's pending flags.
  * @param  UARTx: where x can be from 0 to 1 to select the UART peripheral.
  * @param  UART_FLAG: specifies the flag to clear.
  *          This parameter can be any combination of the following values:
  *            @arg UART_SR_PE
  *            @arg UART_SR_FE
  *            @arg UART_SR_OVR
  * @retval None
  */
void UART_ClearFlag(UART_TypeDef* UARTx, u32 UART_IT)
{
	/* Check the parameters */
	assert_param(IS_UART_ALL_PERIPH(UARTx));
	assert_param(IS_UART_IT_SEL(UART_IT));
	UARTx->SR |= UART_IT;
}

/**
  * @brief  Checks whether the specified UART flag is set or not.
  * @param  UARTx: where x can be from 0 to 1 to select the UART peripheral.
  * @param  UART_FLAG: specifies the flag to clear.
  *          This parameter can be any combination of the following values:
  *            @arg UART_SR_PE
  *            @arg UART_SR_FE
  *            @arg UART_SR_OVR
  * @retval None
  */
ITStatus UART_GetITStatus(UART_TypeDef* UARTx, u32 UART_IT)
{
	ITStatus bitstatus = RESET;
	u32 enablestatus = 0;
	/* Check the parameters */
	assert_param(IS_UART_ALL_PERIPH(UARTx));
	assert_param(IS_UART_IT_GET(UART_IT));
	/**/
	enablestatus = (u32)(UARTx->IE & UART_IT);
	/*  */
	if (((u32)(UARTx->SR & UART_IT) != (u32)RESET) && (enablestatus != (u32)RESET))
	{
		/* */
		bitstatus = SET;
	}
	else
	{
		/* */
		bitstatus = RESET;
	}
	/**/
	return  bitstatus;
}

/**
  * @}
  */

